package com.vf.cloud.pass.mvc.sys.controller;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.vf.cloud.pass.common.constant.SecurityConstant;
import com.vf.cloud.pass.common.datasource.annotation.Tx;
import com.vf.cloud.pass.common.domain.sys.Dept;
import com.vf.cloud.pass.common.domain.sys.Menu;
import com.vf.cloud.pass.common.domain.sys.Role;
import com.vf.cloud.pass.common.domain.sys.RoleMenu;
import com.vf.cloud.pass.common.domain.sys.User;
import com.vf.cloud.pass.common.domain.sys.UserDept;
import com.vf.cloud.pass.common.domain.sys.UserRole;
import com.vf.cloud.pass.common.repository.base.Thumbnail;
import com.vf.cloud.pass.common.util.DateUtil;
import com.vf.cloud.pass.common.util.EncryptUtil;
import com.vf.cloud.pass.common.util.JWTUtil;
import com.vf.cloud.pass.common.util.R;
import com.vf.cloud.pass.common.util.RsaUtil;
import com.vf.cloud.pass.common.util.UuidUtil;
import com.vf.cloud.pass.mvc.biz.service.IThumbnail;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/sys/user")
public class UserController {
	
	@Autowired
	private IThumbnail thumbnailImpl;
	
	@Tx
	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public R<User> update(User model) {
		try {
			if (StrKit.notBlank(model.getId())) {
				if (model.update()) {
					return R.ok(model);
				} else {
					return R.failed("更新失败！");
				}
			} else {
				model.setId(UuidUtil.getUUID());
				if (model.save()) {
					return R.ok(model);
				} else {
					return R.failed("保存失败！");
				}
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}
	
	
	// @SysLog(value = "根据用户名查询用户")
	@GetMapping("/findByUsername/{username}")
	public R<User> findByUsername(@PathVariable String username) {
		User user = User.dao.findFirst("select * from sys_user where username=? and del_flag='0' ", username);
		if (user == null) {
			return R.failed(String.format("用户信息为空 %s", username));
		}

		List<Dept> depts = Dept.dao.find("select name from " + Dept.TABLE_NAME
				+ " where id in (select DEPT_ID from SYS_USER_DEPT where user_id=? ) ", user.getId());

		String deptName = "";
		List<Role> roles;
		String roleName = "";

		if (depts != null && depts.size() > 0) {
			deptName = "";
			for (Dept dept : depts) {
				deptName += dept.getName() + "|";
			}
			user.setDeptName(deptName.substring(0, deptName.length() - 1));
			user.setDeptName(deptName);
		}

		roles = Role.dao.find("select name from " + Role.TABLE_NAME
				+ " where id in (select role_id from sys_user_role where user_id=? ) ", user.getId());
		if (roles != null && roles.size() > 0) {
			roleName = "";
			for (Role role : roles) {
				roleName += role.getName() + "|";
			}
			user.setRoleName(roleName.substring(0, roleName.length() - 1));

			user.setRoleName(roleName);
		}

		List<UserRole> userRoles = UserRole.dao.find("select * from sys_user_role where user_id=? ", user.getId());
		user.setRoles(userRoles);
		List<Menu> menus = Menu.dao.find("SELECT M.PERMS FROM " + Menu.TABLE_NAME + " M "
				+ " WHERE M.ID IN (SELECT RM.MENU_ID FROM " + RoleMenu.TABLE_NAME
				+ " RM ,SYS_USER_ROLE UR WHERE UR.USER_ID=? AND RM.ROLE_ID=UR.ROLE_ID )  AND M.PERMS IS NOT NULL  ",
				user.getId());
		user.setPermissions(menus);
		return R.ok(user);
	}

	@RequestMapping(value = "/info", method = RequestMethod.GET)
	public R<User> info(HttpServletRequest request) {
		String token = request.getHeader(SecurityConstant.HEADER);
		if (StrKit.isBlank(token)) {
			return R.noLogin();
		}
		try {
			token = token.replace(SecurityConstant.TOKEN_SPLIT, "");
			String userId = JWTUtil.getClainByName(token, "userId").asString();
			if (StrKit.isBlank(userId)) {
				return R.noLogin();
			}
			User user = User.dao.findById(userId);
			if (user == null) {
				return R.noLogin();
			}
			user.remove("password");
			return R.ok(user);
		} catch (Exception e) {
			return R.noLogin();
		}
	}

	@GetMapping(value = { "/findList" }, produces = "application/json; charset=utf-8")
	public R<Page<User>> findList(@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "orgId", required = false, defaultValue = "") String orgId,
			@RequestParam(name = "status", required = false, defaultValue = "") String status,
			@RequestParam(name = "isSub", required = false, defaultValue = "0") String isSub,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {
		String sqlExceptSelect = " FROM " + User.TABLE_NAME + " o  WHERE del_flag='0' ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' OR   O.USERNAME LIKE '%" + keywords 
					+ "%' OR O.ORG_NAME LIKE '%"+keywords+"%' OR PHONE LIKE '%"+keywords+"%' ) ";
		}
		if (!StrKit.isBlank(orgId)) {
			sqlExceptSelect += " AND O.ID IN ( SELECT USER_ID FROM SYS_USER_DEPT WHERE  DEPT_ID='" + orgId + "') ";
		}
		if (!StrKit.isBlank(status)) {
			sqlExceptSelect += " AND O.LOCK_FLAG='" + status + "' ";
		}
		if (!StrKit.isBlank(isSub)) {
			sqlExceptSelect += " AND O.IS_SUB_ACCOUNT='" + isSub + "' ";
		}
		sqlExceptSelect += "  ORDER BY   O.UPDATE_TIME desc ";

		Page<User> pages = User.dao.paginate(cur, limit, "select * ", sqlExceptSelect);

		if (pages != null && pages.getList() != null && pages.getList().size() > 0) {
			List<Dept> depts;
			String deptName = "";
			List<Role> roles;
			String roleName = "";
			for (User user : pages.getList()) {
				depts = Dept.dao.find("select name from " + Dept.TABLE_NAME
						+ " where id in (select DEPT_ID from SYS_USER_DEPT where user_id=? ) ", user.getId());
				if (depts != null && depts.size() > 0) {
					deptName = "";
					for (Dept dept : depts) {
						deptName += dept.getName() + "|";
					}
					user.setDeptName(deptName.substring(0, deptName.length() - 1));
				}
				roles = Role.dao.find("select name from " + Role.TABLE_NAME
						+ " where id in (select role_id from sys_user_role where user_id=? ) ", user.getId());
				if (roles != null && roles.size() > 0) {
					roleName = "";
					for (Role role : roles) {
						roleName += role.getName() + "|";
					}
					user.setRoleName(roleName.substring(0, roleName.length() - 1));
				}
			}
		}
		return R.ok(pages);
	}
	
	@GetMapping(value = { "/findSubList" }, produces = "application/json; charset=utf-8")
	public R<List<User>> findSubList(@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "orgId", required = false, defaultValue = "") String orgId,
			@RequestParam(name = "status", required = false, defaultValue = "") String status,
			@RequestParam(name = "isSub", required = false, defaultValue = "1") String isSub) throws Exception {
		String sqlExceptSelect = " FROM " + User.TABLE_NAME + " o  WHERE del_flag='0' ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' OR   O.USERNAME LIKE '%" + keywords 
					+ "%' OR O.ORG_NAME LIKE '%"+keywords+"%' OR PHONE LIKE '%"+keywords+"%' ) ";
		}
		if (!StrKit.isBlank(orgId)) {
			sqlExceptSelect += " AND O.ORG_ID ='"+orgId+"' ";
		}
		if (!StrKit.isBlank(status)) {
			sqlExceptSelect += " AND O.LOCK_FLAG='" + status + "' ";
		}
		if (!StrKit.isBlank(isSub)) {
			sqlExceptSelect += " AND O.IS_SUB_ACCOUNT='" + isSub + "' ";
		}
		sqlExceptSelect += "  ORDER BY O.UPDATE_TIME desc ";

		List<User> users = User.dao.find("select * "+sqlExceptSelect);
		return R.ok(users);
	}

	@Tx
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public R<User> save(@RequestParam(name = "user", required = false) String user,
			@RequestParam(name = "deptIds", required = false) String deptIds,
			@RequestParam(name = "roleIds", required = false) String roleIds) {
		try {

			if (StrKit.isBlank(user)) {
				return R.failed("参数必填!");
			}

			JSONObject userJson = JSONObject.parseObject(user);
			if (userJson == null) {
				return R.failed("参数必填!");
			}

			User u = new User();

			if (userJson.containsKey("id")) {
				u.setId(userJson.getString("id"));
			}

			if (userJson.containsKey("username")) {
				if (StrKit.isBlank(userJson.getString("username"))) {
					return R.failed("参数必填!");
				}
				u.setUsername(userJson.getString("username"));
			} else {
				return R.failed("参数必填!");
			}

			if (userJson.containsKey("name")) {
				u.setName(userJson.getString("name"));
			}

			if (userJson.containsKey("phone")) {
				u.setPhone(userJson.getString("phone"));
			}
			
			if (userJson.containsKey("orgName")) {
				u.setOrgName(userJson.getString("orgName"));
			}

//			SimpleUser simpleUser = SecurityUtils.getUser();
			if (StrKit.notBlank(u.getId())) {
//				if (simpleUser != null) {
//					u.setUpdateBy(simpleUser.getUsername());
//				}
				u.setUpdateTime(DateUtil.getLocalDateTime());
				if (u.update()) {
					User.saveDeptIds(u.getId(), deptIds);
					User.saveRoleIds(u.getId(), roleIds);
					return R.ok(u);
				} else {
					return R.failed("更新失败！");
				}
			} else {
				String id = UuidUtil.getUUID();
				u.setId(id);
				u.setOrgId(id);
				u.setPassword(EncryptUtil.encrypt("Xxc@admin2022"));
				u.setCreateTime(DateUtil.getLocalDateTime());
//				if (simpleUser != null) {
//					u.setCreateBy(simpleUser.getUsername());
//				}
				if (u.save()) {
					User.saveDeptIds(u.getId(), deptIds);
					User.saveRoleIds(u.getId(), roleIds);
					return R.ok(u);
				} else {
					return R.failed("保存失败！");
				}
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}
	
	@Tx
	@RequestMapping(value = "/saveSubUserBatch", method = RequestMethod.POST)
	public R<User> saveSubUserBatch(@RequestBody String json) {
		try {

			if (StrKit.isBlank(json)) {
				return R.failed("参数必填!");
			}
			JSONObject jsonObj = JSONObject.parseObject(json);
			
			String orgId = jsonObj.getString("orgId");
			if (StrKit.isBlank(orgId)) {
				return R.failed("参数必填!");
			}
			
			JSONArray users = jsonObj.getJSONArray("users");
			if(users == null) {
				return R.failed("参数必填!");
			}
			
			String roleIds = jsonObj.getString("roleIds");
			
			if(users.size()==0) {
				Db.delete("UPDATE "+User.TABLE_NAME+" SET DEL_FLAG='1' WHERE ORG_ID=? AND IS_SUB_ACCOUNT='1' ",orgId);
				return R.ok();
			}
			
			StringBuffer ids = new StringBuffer();
			for (Object object : users) {
				JSONObject userJson = (JSONObject) object;
				if(userJson.containsKey("orgId") && StrKit.notBlank(userJson.getString("orgId"))) {
					String id = UuidUtil.getUUID();
					if (userJson.containsKey("id") && StrKit.notBlank(userJson.getString("id"))) {
						id = userJson.getString("id");
					}
					User user = User.dao.findFirst("select * from "+User.TABLE_NAME+" WHERE ID=? AND ORG_ID=? AND IS_SUB_ACCOUNT='1' ",id,userJson.getString("orgId"));
					if(user==null) {
						user = new User();
						user.setId(id);
						user.setOrgId(userJson.getString("orgId"));
						user.setIsSubAccount("1");
						user.setName(userJson.getString("name"));
						user.setUsername(userJson.getString("phone"));
						user.setPhone(userJson.getString("phone"));
						user.setPassword(EncryptUtil.encrypt("Xxc@2022"));
						user.setCreateTime(DateUtil.getLocalDateTime());
						user.save();
					}
					if (userJson.containsKey("name")) {
						user.setName(userJson.getString("name"));
					}
					if (userJson.containsKey("phone")) {
						user.setPhone(userJson.getString("phone"));
						user.setUsername(userJson.getString("phone"));
					}
					user.setUpdateTime(DateUtil.getLocalDateTime());
					if(user.update()) {
						if(StrKit.notBlank(roleIds)) {
							User.saveRoleIds(user.getId(), roleIds);
						}
					}
					ids.append("'").append(user.getId()).append("',");
				}
			}
			if(ids.length()>0) {
				Db.delete("UPDATE "+User.TABLE_NAME+" SET DEL_FLAG='1' WHERE ORG_ID=? AND IS_SUB_ACCOUNT='1' AND ID NOT IN ("+ids.substring(0, ids.length()-1)+") ",orgId);
			}
			return R.ok();
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed(e.getMessage());
		}
	}

	@Tx
	@RequestMapping(value = "/delete", method = RequestMethod.GET)
	public R<String> delete(@RequestParam(name = "id") String id) throws Exception {
		try {
			User user = User.dao.findById(id);
			if (user == null)
				return R.failed("数据不存在，刷新后尝试!");
			if (StrKit.equals(user.getUsername(), "system"))
				return R.failed("默认数据不可以删除!");
			user.setDelFlag("1");
			user.setLockFlag("9");
//			SimpleUser simpleUser = SecurityUtils.getUser();
//			if (simpleUser != null) {
//				user.setUpdateBy(simpleUser.getUsername());
//			}
//			user.setUpdateTime(DateUtil.getLocalDateTime());
			if (user.update())
				return R.ok();
			return R.failed("失败！");
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@GetMapping(value = { "/getDeptIdsById" }, produces = "application/json; charset=utf-8")
	public R<List<String>> getDeptIdsById(@RequestParam(name = "userId") String userId) {
		List<String> userDeptIds = new LinkedList<String>();
		List<UserDept> list = UserDept.dao.find("select * from sys_user_dept where user_id=? ", userId);
		for (UserDept ut : list) {
			userDeptIds.add(ut.getDeptId());
		}
		return R.ok(userDeptIds);
	}

	@GetMapping(value = { "/getRoleIdsById" }, produces = "application/json; charset=utf-8")
	public R<List<String>> getRoleIdsById(@RequestParam(name = "userId") String userId) {
		List<String> userRoleIds = new LinkedList<String>();
		List<UserRole> list = UserRole.dao.find("select * from sys_user_role where user_id=? ", userId);
		for (UserRole ur : list) {
			userRoleIds.add(ur.getRoleId());
		}
		return R.ok(userRoleIds);
	}
	
	
	@GetMapping(value = { "/getOrgOptions" }, produces = "application/json; charset=utf-8")
	public R<List<User>> getOrgOptions(@RequestParam(name = "keywords") String keywords) {
		List<User> list=User.dao.find("select org_id,org_name from "+User.TABLE_NAME+" where is_sub_account='0' and org_name like '%"+keywords+"%' ");
		return R.ok(list);
	}
	
	@RequestMapping(value = "updatePwd", method = RequestMethod.POST)
	public R<String> updatePwd(HttpServletRequest request, @RequestBody String param) throws Exception {
		JSONObject json = JSONObject.parseObject(param);
		String id = json.getString("id");
		String newPassword = json.getString("newPassword");
		String oldPassword = json.getString("oldPassword");
		
		if(StrKit.isBlank(oldPassword)) {
			return R.failed("旧密码不能为空!");
		}
		
		if(StrKit.isBlank(newPassword)) {
			return R.failed("新密码不能为空!");
		}
		
		try {
			id = RsaUtil.decrypt(id, SecurityConstant.PRIVATE_KEY);
			newPassword = RsaUtil.decrypt(newPassword, SecurityConstant.PRIVATE_KEY);
			//oldPassword = RsaUtil.decrypt(oldPassword, SecurityConstant.PRIVATE_KEY);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("解密信息失败!");
		}

		User user = User.dao.findById(id);
		if (user == null) {
			return R.failed("用户不存在.");
		}
		oldPassword = RsaUtil.decrypt(oldPassword, SecurityConstant.PRIVATE_KEY);
		if (!EncryptUtil.matches(oldPassword, user.getPassword())) {
			return R.failed("旧密码错误.");
		}
		user.setPassword(EncryptUtil.encrypt(newPassword));
		user.setUpdateTime(DateUtil.getLocalDateTime());
		if (user.update()) {
			return R.ok("密码修改成.");
		} else {
			return R.failed("密码修改成.");
		}
	}

	@GetMapping("/deleteImage/{id}")
	public R<String> deleteImage(@PathVariable String id) {
		try {
			thumbnailImpl.deleteById(id);
			return R.ok();
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}
	
	@RequestMapping(value = "/uploadImage", method = RequestMethod.POST)
	public R<String> uploadImage(MultipartFile file,String id) {
		try {
			if(file==null) {
				return R.failed("参数必填！");
			}
			if(StrKit.isBlank(id)) {
				return R.failed("参数必填！");
			}
			Thumbnail thumbnailEntity = null;
			thumbnailImpl.deleteById(id);
			thumbnailEntity = new Thumbnail();
			thumbnailEntity.setId(id);
			thumbnailEntity.setSize(file.getSize());
			thumbnailEntity.setName(file.getName());
			thumbnailEntity.setContentType(file.getContentType());
			thumbnailEntity.setUploadDate(new Date(System.currentTimeMillis()));
			thumbnailEntity.setContent(new Binary(file.getBytes()));
			thumbnailImpl.save(thumbnailEntity);
			return R.ok(thumbnailEntity.getId());
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}
	
	@GetMapping(value = "/thumbnail/{id}", produces = { MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE })
	@ResponseBody
	public byte[] image(@PathVariable String id) {
		byte[] data = null;
		Thumbnail thumbnail = thumbnailImpl.findById(id);
		if (thumbnail != null) {
			data = thumbnail.getContent().getData();
		}
		return data;
	}

}
